package hn.cch.apache.commons.math3;

import org.apache.commons.math3.stat.StatUtils;
import org.apache.commons.math3.stat.correlation.Covariance;
import org.apache.commons.math3.stat.correlation.PearsonsCorrelation;
import org.apache.commons.math3.stat.descriptive.moment.StandardDeviation;
import org.apache.commons.math3.stat.regression.RegressionResults;
import org.apache.commons.math3.stat.regression.SimpleRegression;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;


/**
 * 统计计算
 */
public class TestMath3 {

    private static final Logger logger = LoggerFactory.getLogger(TestMath3.class);


    @Test
    public void calculateCorrelationCoefficient() {

        double[] X = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
        double[] Y = new double[]{1.5, 2.4, 3.2, 4.1, 5.5, 6.7, 7.3, 8.6, 9.9};

        // 计算相关系数
        double covariance = new Covariance().covariance(X, Y);
        double varianceX = StatUtils.variance(X);
        double varianceY = StatUtils.variance(Y);
        double correlation = covariance / Math.sqrt(varianceX * varianceY);
        logger.info("correlation:{}", correlation);

        PearsonsCorrelation pearsonsCorrelation = new PearsonsCorrelation();
        logger.info("PearsonsCorrelation:{}", pearsonsCorrelation.correlation(X, Y));


    }

    @Test
    public void testRegression() {
        List<double[]> temp = new ArrayList<>();
        for (double x = 0; x <= 10; x += 0.1) {
            double y = 1.5 * x + 0.5;
            y += Math.random() * 2 - 1; // 随机数
            double[] xy = {x, y};
            temp.add(xy);
        }
        double[][] data = temp.stream().toArray(double[][]::new);
        List<double[]> fitData = new ArrayList<>();
        SimpleRegression regression = new SimpleRegression();
        regression.addData(data); // 数据集
        /*
         * RegressionResults 中是拟合的结果
         * 其中重要的几个参数如下：
         *   parameters:
         *      0: b
         *      1: k
         *   globalFitInfo
         *      0: 平方误差之和, SSE
         *      1: 平方和, SST
         *      2: R 平方, RSQ
         *      3: 均方误差, MSE
         *      4: 调整后的 R 平方, adjRSQ
         *
         * */
        RegressionResults results = regression.regress();
        double b = results.getParameterEstimate(0);
        double k = results.getParameterEstimate(1);

        // 重新计算生成拟合曲线
        for (double[] datum : data) {
            double[] xy = {datum[0], k * datum[0] + b};
            fitData.add(xy);
        }


    }

    @Test
    public void testStatUtils() {
        double[] x = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        double[] y = new double[]{10, 11, 12, 13, 14, 15, 16, 17, 18, 19};

        double sumX = StatUtils.sum(x);
        double sumSqX = StatUtils.sumSq(x);
        double meanX = StatUtils.mean(x);
        double gmMeanX = StatUtils.geometricMean(x);
        logger.info("sumX={},sumSqX={},meanX={},gmMeanX={}", sumX, sumSqX, meanX, gmMeanX);

        Double varianceX = StatUtils.variance(x);
        logger.info("varianceX={}", varianceX);
        logger.info("Math.sqrt:varianceX={}", Math.sqrt(varianceX));


        StandardDeviation standardDeviation = new StandardDeviation(true);
        Double stdDevX = standardDeviation.evaluate(x);
        logger.info("stdDevX={}", stdDevX);


    }

    @Test
    public void test() {


        // 偏度
        // Skewness skewness = new Skewness();
        // System.out.println(skewness.evaluate(doubleListArray(R)));


    }


}
